﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LiftEmulator.Model
{
    /// <summary>
    /// Этаж
    /// </summary>
    public class Floor
    {
        /// <summary>
        /// Максимальная длина очереди
        /// </summary>
        const int maxQueueLength = 9;

        /// <summary>
        /// Порядковый номер этажа
        /// </summary>
        public int Number { get; private set; }

        /// <summary>
        /// Внутреннее хранилище для очереди ожидающих
        /// </summary>
        private Queue<People> queue = new Queue<People>();


        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="number">Номер этажа</param>
        public Floor(int number)
        {
            Number = number;
        }

        #region Дополнительные свойства и методы

        /// <summary>
        /// Если в очереди есть человек, то он обязательно нажимает кнопку вызова лифта
        /// </summary>
        public bool IsButtonPushed
        {
            get
            {                
                return queue.Any();
            }
        }

        /// <summary>
        /// Есть ли ещё место в очереди
        /// </summary>
        public bool IsFull
        {
            get
            {
                return queue.Count == maxQueueLength;
            }
        }

        /// <summary>
        /// Количество человек в очереди
        /// </summary>
        public int Count
        {
            get
            {
                return queue.Count;
            }
        }
        
        /// <summary>
        /// Поместить человека в очередь
        /// </summary>
        /// <param name="people">человек</param>
        public void Enqueue(People people)
        {            
            queue.Enqueue(people);
            RaiseFloorChangeEvent(true, people);
        }      
        

        /// <summary>
        /// Забрать человека из очереди
        /// </summary>
        /// <returns></returns>
        public People Dequeue()
        {
            var people = queue.Dequeue();
            RaiseFloorChangeEvent(false, people);
            return people;
        }

        #endregion

        #region Событие Change (изменение очереди на этаже)

        /// <summary>
        /// Аргументы события на изменение очереди
        /// </summary>
        public class FloorChangeEventArgs : EventArgs
        {
            /// <summary>
            /// true - человек пришел в очередь, false - человек ушел из очереди
            /// </summary>
            public bool IsEnqueue { get; private set; }

            /// <summary>
            /// человек
            /// </summary>
            public People ChangedPeople { get; private set; }

            /// <summary>
            /// Новое состояние очереди
            /// </summary>
            public IEnumerable<People> NewQueue { get; private set; }

            /// <summary>
            /// Конструктор
            /// </summary>
            /// <param name="isEnqueue">true - человек пришел в очередь, false - человек ушел из очереди</param>
            /// <param name="changedPeople">человек</param>
            /// <param name="newQueue">новое состояние очереди</param>
            public FloorChangeEventArgs(bool isEnqueue, People changedPeople, IEnumerable<People> newQueue)
            {
                this.IsEnqueue = isEnqueue;
                this.ChangedPeople = changedPeople;
                this.NewQueue = newQueue;
            }
        }

        /// <summary>
        /// Изменение очереди на этаже
        /// </summary>
        public event EventHandler<FloorChangeEventArgs> FloorChange;

        /// <summary>
        /// Генерация события на изменение очереди
        /// </summary>
        /// <param name="isEnqueue">true - человек пришел в очередь, false - человек ушел из очереди</param>
        /// <param name="people">человек</param>
        private void RaiseFloorChangeEvent(bool isEnqueue, People people)
        {
            var floorChange = FloorChange;
            if (floorChange != null) floorChange(this, new FloorChangeEventArgs(isEnqueue, people, queue));
        }
        #endregion
    }
}
